package org.cybzacg.convert.config;

import org.cybzacg.convert.enums.CopyMode;
import org.cybzacg.convert.enums.FieldFilterStrategy;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 拷贝配置类
 * 封装属性拷贝的所有配置选项，支持链式调用和验证
 * 
 * @author PropertyCopier Implementation
 * @version 1.0.0
 */
public class CopyConfig {
    
    // 默认配置常量
    private static final CopyMode DEFAULT_COPY_MODE = CopyMode.SHALLOW;
    private static final FieldFilterStrategy DEFAULT_FILTER_STRATEGY = FieldFilterStrategy.INCLUDE_ONLY;
    private static final boolean DEFAULT_IGNORE_NULL_VALUES = false;
    private static final boolean DEFAULT_IGNORE_READ_ONLY = true;
    private static final boolean DEFAULT_ENABLE_CACHE = true;
    private static final int DEFAULT_MAX_DEPTH = 10;
    private static final int DEFAULT_CACHE_SIZE = 1000;
    
    // 基础配置
    private CopyMode defaultMode;
    private FieldFilterStrategy filterStrategy;
    
    // 字段过滤配置
    private Set<String> includedFields;
    private Set<String> excludedFields;
    private Set<Class<? extends Annotation>> includeAnnotations;
    private Set<Class<? extends Annotation>> excludeAnnotations;
    private Set<Pattern> includePatterns;
    private Set<Pattern> excludePatterns;
    
    // 行为配置
    private boolean ignoreNullValues;
    private boolean ignoreReadOnly;
    private boolean enableCache;
    private int maxDepth;
    private int cacheSize;
    
    // 性能配置
    private boolean enableParallelCopy;
    private int parallelThreshold;
    private long timeoutMillis;
    
    // 验证配置
    private boolean enableValidation;
    private boolean failOnMissingField;
    private boolean failOnTypeMismatch;
    
    // 调试配置
    private boolean enableDebug;
    private boolean enableStatistics;
    
    /**
     * 默认构造函数
     */
    public CopyConfig() {
        this.defaultMode = DEFAULT_COPY_MODE;
        this.filterStrategy = DEFAULT_FILTER_STRATEGY;
        this.includedFields = new HashSet<>();
        this.excludedFields = new HashSet<>();
        this.includeAnnotations = new HashSet<>();
        this.excludeAnnotations = new HashSet<>();
        this.includePatterns = new HashSet<>();
        this.excludePatterns = new HashSet<>();
        this.ignoreNullValues = DEFAULT_IGNORE_NULL_VALUES;
        this.ignoreReadOnly = DEFAULT_IGNORE_READ_ONLY;
        this.enableCache = DEFAULT_ENABLE_CACHE;
        this.maxDepth = DEFAULT_MAX_DEPTH;
        this.cacheSize = DEFAULT_CACHE_SIZE;
        this.enableParallelCopy = false;
        this.parallelThreshold = 100;
        this.timeoutMillis = 5000L;
        this.enableValidation = true;
        this.failOnMissingField = false;
        this.failOnTypeMismatch = false;
        this.enableDebug = false;
        this.enableStatistics = false;
    }
    
    /**
     * 拷贝构造函数
     * 
     * @param other 要拷贝的配置对象
     */
    public CopyConfig(CopyConfig other) {
        this.defaultMode = other.defaultMode;
        this.filterStrategy = other.filterStrategy;
        this.includedFields = new HashSet<>(other.includedFields);
        this.excludedFields = new HashSet<>(other.excludedFields);
        this.includeAnnotations = new HashSet<>(other.includeAnnotations);
        this.excludeAnnotations = new HashSet<>(other.excludeAnnotations);
        this.includePatterns = new HashSet<>(other.includePatterns);
        this.excludePatterns = new HashSet<>(other.excludePatterns);
        this.ignoreNullValues = other.ignoreNullValues;
        this.ignoreReadOnly = other.ignoreReadOnly;
        this.enableCache = other.enableCache;
        this.maxDepth = other.maxDepth;
        this.cacheSize = other.cacheSize;
        this.enableParallelCopy = other.enableParallelCopy;
        this.parallelThreshold = other.parallelThreshold;
        this.timeoutMillis = other.timeoutMillis;
        this.enableValidation = other.enableValidation;
        this.failOnMissingField = other.failOnMissingField;
        this.failOnTypeMismatch = other.failOnTypeMismatch;
        this.enableDebug = other.enableDebug;
        this.enableStatistics = other.enableStatistics;
    }
    
    // Getter方法
    public CopyMode getDefaultMode() { return defaultMode; }
    public FieldFilterStrategy getFilterStrategy() { return filterStrategy; }
    public Set<String> getIncludedFields() { return new HashSet<>(includedFields); }
    public Set<String> getExcludedFields() { return new HashSet<>(excludedFields); }
    public Set<Class<? extends Annotation>> getIncludeAnnotations() { return new HashSet<>(includeAnnotations); }
    public Set<Class<? extends Annotation>> getExcludeAnnotations() { return new HashSet<>(excludeAnnotations); }
    public Set<Pattern> getIncludePatterns() { return new HashSet<>(includePatterns); }
    public Set<Pattern> getExcludePatterns() { return new HashSet<>(excludePatterns); }
    public boolean isIgnoreNullValues() { return ignoreNullValues; }
    public boolean isIgnoreReadOnly() { return ignoreReadOnly; }
    public boolean isEnableCache() { return enableCache; }
    public int getMaxDepth() { return maxDepth; }
    public int getCacheSize() { return cacheSize; }
    public boolean isEnableParallelCopy() { return enableParallelCopy; }
    public int getParallelThreshold() { return parallelThreshold; }
    public long getTimeoutMillis() { return timeoutMillis; }
    public boolean isEnableValidation() { return enableValidation; }
    public boolean isFailOnMissingField() { return failOnMissingField; }
    public boolean isFailOnTypeMismatch() { return failOnTypeMismatch; }
    public boolean isEnableDebug() { return enableDebug; }
    public boolean isEnableStatistics() { return enableStatistics; }
    
    // Setter方法（支持链式调用）
    public CopyConfig setDefaultMode(CopyMode defaultMode) {
        this.defaultMode = defaultMode != null ? defaultMode : DEFAULT_COPY_MODE;
        return this;
    }
    
    public CopyConfig setFilterStrategy(FieldFilterStrategy filterStrategy) {
        this.filterStrategy = filterStrategy != null ? filterStrategy : DEFAULT_FILTER_STRATEGY;
        return this;
    }
    
    public CopyConfig setIncludedFields(Set<String> includedFields) {
        this.includedFields = includedFields != null ? new HashSet<>(includedFields) : new HashSet<>();
        return this;
    }
    
    public CopyConfig setExcludedFields(Set<String> excludedFields) {
        this.excludedFields = excludedFields != null ? new HashSet<>(excludedFields) : new HashSet<>();
        return this;
    }
    
    public CopyConfig setIncludeAnnotations(Set<Class<? extends Annotation>> includeAnnotations) {
        this.includeAnnotations = includeAnnotations != null ? new HashSet<>(includeAnnotations) : new HashSet<>();
        return this;
    }
    
    public CopyConfig setExcludeAnnotations(Set<Class<? extends Annotation>> excludeAnnotations) {
        this.excludeAnnotations = excludeAnnotations != null ? new HashSet<>(excludeAnnotations) : new HashSet<>();
        return this;
    }
    
    public CopyConfig setIgnoreNullValues(boolean ignoreNullValues) {
        this.ignoreNullValues = ignoreNullValues;
        return this;
    }
    
    public CopyConfig setIgnoreReadOnly(boolean ignoreReadOnly) {
        this.ignoreReadOnly = ignoreReadOnly;
        return this;
    }
    
    public CopyConfig setEnableCache(boolean enableCache) {
        this.enableCache = enableCache;
        return this;
    }
    
    public CopyConfig setMaxDepth(int maxDepth) {
        this.maxDepth = Math.max(0, maxDepth);
        return this;
    }
    
    public CopyConfig setCacheSize(int cacheSize) {
        this.cacheSize = Math.max(0, cacheSize);
        return this;
    }
    
    // 便捷方法
    public CopyConfig addIncludedField(String fieldName) {
        if (fieldName != null && !fieldName.trim().isEmpty()) {
            this.includedFields.add(fieldName.trim());
        }
        return this;
    }
    
    public CopyConfig addExcludedField(String fieldName) {
        if (fieldName != null && !fieldName.trim().isEmpty()) {
            this.excludedFields.add(fieldName.trim());
        }
        return this;
    }
    
    public CopyConfig addIncludeAnnotation(Class<? extends Annotation> annotationClass) {
        if (annotationClass != null) {
            this.includeAnnotations.add(annotationClass);
        }
        return this;
    }
    
    public CopyConfig addExcludeAnnotation(Class<? extends Annotation> annotationClass) {
        if (annotationClass != null) {
            this.excludeAnnotations.add(annotationClass);
        }
        return this;
    }
    
    public CopyConfig addIncludePattern(String regex) {
        if (regex != null && !regex.trim().isEmpty()) {
            try {
                this.includePatterns.add(Pattern.compile(regex.trim()));
            } catch (Exception e) {
                // 忽略无效的正则表达式
            }
        }
        return this;
    }
    
    public CopyConfig addExcludePattern(String regex) {
        if (regex != null && !regex.trim().isEmpty()) {
            try {
                this.excludePatterns.add(Pattern.compile(regex.trim()));
            } catch (Exception e) {
                // 忽略无效的正则表达式
            }
        }
        return this;
    }
    
    public CopyConfig enableParallelCopy(boolean enable) {
        this.enableParallelCopy = enable;
        return this;
    }
    
    public CopyConfig setParallelThreshold(int threshold) {
        this.parallelThreshold = Math.max(1, threshold);
        return this;
    }
    
    public CopyConfig setTimeout(long timeoutMillis) {
        this.timeoutMillis = Math.max(0, timeoutMillis);
        return this;
    }
    
    public CopyConfig enableValidation(boolean enable) {
        this.enableValidation = enable;
        return this;
    }
    
    public CopyConfig failOnMissingField(boolean fail) {
        this.failOnMissingField = fail;
        return this;
    }
    
    public CopyConfig failOnTypeMismatch(boolean fail) {
        this.failOnTypeMismatch = fail;
        return this;
    }
    
    public CopyConfig enableDebug(boolean enable) {
        this.enableDebug = enable;
        return this;
    }
    
    public CopyConfig enableStatistics(boolean enable) {
        this.enableStatistics = enable;
        return this;
    }
    
    /**
     * 验证配置的有效性
     * 
     * @return 验证结果
     */
    public ValidationResult validate() {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();
        
        // 验证基础配置
        if (defaultMode == null) {
            errors.add("默认拷贝模式不能为空");
        }
        
        if (filterStrategy == null) {
            errors.add("字段过滤策略不能为空");
        }
        
        // 验证字段配置
        if (filterStrategy.requiresFieldList() && includedFields.isEmpty() && excludedFields.isEmpty()) {
            warnings.add("当前过滤策略需要字段配置，但未配置任何字段");
        }
        
        if (filterStrategy.requiresAnnotationConfig() && includeAnnotations.isEmpty() && excludeAnnotations.isEmpty()) {
            warnings.add("当前过滤策略需要注解配置，但未配置任何注解");
        }
        
        // 验证性能配置
        if (maxDepth < 0) {
            errors.add("最大深度不能为负数");
        }
        
        if (cacheSize <= 0) {
            errors.add("缓存大小必须大于0");
        }
        
        if (parallelThreshold <= 0) {
            errors.add("并行拷贝阈值必须大于0");
        }
        
        if (timeoutMillis < 0) {
            errors.add("超时时间不能为负数");
        }
        
        // 验证模式兼容性
        if (defaultMode.requiresRecursion() && maxDepth == 0) {
            warnings.add("深拷贝模式建议设置最大深度限制");
        }
        
        return new ValidationResult(errors.isEmpty(), errors, warnings);
    }
    
    /**
     * 创建默认配置
     * 
     * @return 默认配置实例
     */
    public static CopyConfig createDefault() {
        return new CopyConfig();
    }
    
    /**
     * 创建浅拷贝配置
     * 
     * @return 浅拷贝配置实例
     */
    public static CopyConfig createShallow() {
        return new CopyConfig().setDefaultMode(CopyMode.SHALLOW);
    }
    
    /**
     * 创建深拷贝配置
     * 
     * @return 深拷贝配置实例
     */
    public static CopyConfig createDeep() {
        return new CopyConfig()
            .setDefaultMode(CopyMode.DEEP)
            .setMaxDepth(5);
    }
    
    /**
     * 创建高性能配置
     * 
     * @return 高性能配置实例
     */
    public static CopyConfig createHighPerformance() {
        return new CopyConfig()
            .setDefaultMode(CopyMode.SHALLOW)
            .setEnableCache(true)
            .setCacheSize(2000)
            .enableParallelCopy(true)
            .setParallelThreshold(50)
            .setIgnoreNullValues(true)
            .setIgnoreReadOnly(true);
    }
    
    @Override
    public String toString() {
        return String.format("CopyConfig{mode=%s, strategy=%s, cache=%s, maxDepth=%d}", 
            defaultMode, filterStrategy, enableCache, maxDepth);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        CopyConfig that = (CopyConfig) obj;
        return Objects.equals(defaultMode, that.defaultMode) &&
               Objects.equals(filterStrategy, that.filterStrategy) &&
               Objects.equals(includedFields, that.includedFields) &&
               Objects.equals(excludedFields, that.excludedFields) &&
               ignoreNullValues == that.ignoreNullValues &&
               ignoreReadOnly == that.ignoreReadOnly &&
               enableCache == that.enableCache &&
               maxDepth == that.maxDepth;
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(defaultMode, filterStrategy, includedFields, excludedFields, 
                          ignoreNullValues, ignoreReadOnly, enableCache, maxDepth);
    }
    
    /**
     * 验证结果类
     */
    public static class ValidationResult {
        private final boolean valid;
        private final List<String> errors;
        private final List<String> warnings;
        
        public ValidationResult(boolean valid, List<String> errors, List<String> warnings) {
            this.valid = valid;
            this.errors = new ArrayList<>(errors);
            this.warnings = new ArrayList<>(warnings);
        }
        
        public boolean isValid() { return valid; }
        public List<String> getErrors() { return new ArrayList<>(errors); }
        public List<String> getWarnings() { return new ArrayList<>(warnings); }
        
        public boolean hasErrors() { return !errors.isEmpty(); }
        public boolean hasWarnings() { return !warnings.isEmpty(); }
        
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("ValidationResult{valid=").append(valid);
            if (hasErrors()) {
                sb.append(", errors=").append(errors);
            }
            if (hasWarnings()) {
                sb.append(", warnings=").append(warnings);
            }
            sb.append('}');
            return sb.toString();
        }
    }
}
